sub cleanMapArtefacts()
  dim t as uinteger
  dim s as ubyte
  dim adrLayer as uinteger
   'clean the object tile map 
  FOR t = 0 to 767
    POKE AdrScreenObjectsTileMap + t,0
  NEXT t
  
  'clean layers 
  MemCopy(empty_layer,AdrUnionLayer,96)
  for s = 0 to 9
        adrLayer = AdrInicioCapasActiveScreen+(97*s)
        poke adrLayer,0
        MemCopy(empty_layer,adrLayer+1,96)      
  next s 
  
  'clean Limits  
  FOR t = 0 to 120   'limpia 121 posicio
    POKE AdrScreenLimits + t,0
  NEXT t
   

end sub

sub musicInput()
         #IFDEF SONIDO_ACTIVADO
          SetSlot3(6)
            'SE PRESIONA W PARA REPRODUCIR 
            IF  MultiKeys(Teclas(REPM)) then
                'si no esta en play
                IF statusRepAy <> 1 then 
                    ejecutaSonidoAy(reproductor_en_play)              
                END IF
            'SE PRESIONA E PARA PARAR
            ELSE IF MultiKeys(Teclas(STOPM)) then
            'si esta en play
                IF statusRepAy = 1 then
                    ejecutaSonidoAy(reproductor_en_stop)
                END IF            
            ' SE PRESIONA R PARA PAUSAR   
            ELSE IF MultiKeys(Teclas(PAUSEM)) then
                'si esta en play
                IF statusRepAy = 1 then
                    ejecutaSonidoAy(reproductor_en_pause)
                END IF
            END IF
            SetSlot3(0)
        #ENDIF
end sub


SUB changeToCursor()
    Teclas(IZQUIERDA)=KEY5 
    Teclas(DERECHA)=KEY8
    Teclas(ABAJO)=KEY6
    Teclas(ARRIBA)=KEY7
    Teclas(INTERAC)=KEY0
END SUB

sub changeToStandardKeys()

     Teclas(IZQUIERDA)=KEYO 
    Teclas(DERECHA)=KEYP
    Teclas(ABAJO)=KEYA
    Teclas(ARRIBA)=KEYQ
    Teclas(INTERAC)=KEYL
    Teclas(SOLTAR)=KEYK
    Teclas(INFO)=KEYI
    Teclas(REPM)=KEYR
    Teclas(STOPM)=KEYS
    Teclas(PAUSEM)=KEYW
    keyAsciiCodes(1)= "O"
    keyAsciiCodes(2)= "P"
    keyAsciiCodes(3)= "Q"
    keyAsciiCodes(4)= "A"
    keyAsciiCodes(5)= "L"
    keyAsciiCodes(6)= "K"
    keyAsciiCodes(7)= "I"
    keyAsciiCodes(8)= "R"
    keyAsciiCodes(9)= "S"
    keyAsciiCodes(10)= "W"
end sub

SUB changeToSinclair()
IF sinclairPort = 2 then
    Teclas(IZQUIERDA)=KEY1
    Teclas(DERECHA)=KEY2
    Teclas(ABAJO)=KEY3
    Teclas(ARRIBA)=KEY4
    Teclas(INTERAC)=KEY5
else 
    Teclas(IZQUIERDA)=KEY6
    Teclas(DERECHA)=KEY7
    Teclas(ABAJO)=KEY8
    Teclas(ARRIBA)=KEY9
    Teclas(INTERAC)=KEY0
end if
END SUB


'fill the message variable with spaces to leave as before
 sub limpiaVariableTextMessage(length as ubyte)
  dim n as ubyte
  for n = 0 to length-1
        poke (@textMessage-amount_caracter_to_rewind+n),32
    next n

end sub
 
 
 function getTextLength(textAdr as uinteger) as ubyte
  dim caracter as ubyte
  dim n as uinteger
  
  caracter = peek (textAdr+n)
    
  while caracter <> 35
        caracter =peek (textAdr+n)
        n = n +1
  wend    
  
  return n-1
 end function
 
 sub WriteToTextVariable(textAdr as uinteger, length as ubyte)
   'write the text into the variable textMessage
   dim n as ubyte
   dim caracter as ubyte
   n = 0
   
   for n = 0 to length -1
     caracter =peek (textAdr+n)
     poke (@textMessage-amount_caracter_to_rewind+n,caracter)
   next n 
end sub



SUB RedefinirTeclas()
    'dim guardaLetra as string
    dim valor as string
    dim valorNumerico as ubyte
    dim temporal as string
    DIM n AS UByte
    dim x as ubyte
    dim buclePausa as uinteger
    dim bloqueo as ubyte
    'DIM k AS UInteger
    'switch2NormalScreenSWR()
    CLS
    ' Imprimimos la cabecera
     'bloque mayuscula
    bloqueo = peek (23658) 
    if  bloqueo <> 8 then
        poke 23658,8
    end if
   
    SetSlot3(6)
    printFzxSetFontAddr(hemery_font)  '  hemery_font
   
    printFzxAt(0,0) :   printFzxStr("PULSA UNA TECLA PARA:") 
    'TECLA PARA:
    
    'refreshScreen()
    ' Para cada una de las 5 teclas
    FOR n=1 TO 10
        for x = 2 to 17
             print at x,0;"                             "
        next x
        refreshScreen()
        SetSlot3(6)
        ' Imprimimos el nombre de la tecla
        printFzxSetFontAddr(hemery_font)
        printFzxAt(30,60) :   printFzxStr(TeclasS(n))
        printFzxAt(60,30) : printFzxStr("LA TECLA ACTUAL")
        printFzxAt(90,85) : printFzxStr("ES:" + keyAsciiCodes(n))
   
        refreshScreen()
       
        
        
        refreshScreen()
        Teclas(n) = LeerTecla()
        
        keyAsciiCodes(n)= INKEY$
        SetSlot3(6)
        printFzxAt(120,98) : printFzxStr(keyAsciiCodes(n))
        BEEP 0.04,8: BEEP 0.04,12
        refreshScreen()
        
        for buclePausa = 1 to 250
         ejecutaSonidoAy(procesa_una_nota)
        next buclePausa
    NEXT n
    SetSlot3(0)
    
    
        poke 23658,16
    
END SUB


' - Devuelve el código de la tecla pulsada -----------------
' Devuelve:
'   UInteger: Código de la tecla pulsada
FUNCTION LeerTecla() AS UInteger
    ' Declaramos k con el valor 0 por defecto
    DIM k AS UInteger = 0
    
    ' Esperamos hasta que no se pulse nada
    WHILE GetKeyScanCode() <> 0
    WEND
    
    ' Repetimos mientras no se haya pulsado una tecla
    WHILE k = 0
        ' Leemos la tecla pulsada
        k = GetKeyScanCode()  
         ejecutaSonidoAy(procesa_una_nota)
           
    WEND
    
    ' Devolvemos el código de la tecla pulsada
    RETURN k
END FUNCTION




sub compraPececito()
dim textAdr as uinteger
dim textLength as ubyte
saveUpperThirdOfScreen()
borraContenidoDialogoTexto(16384)

textAdr = t_mc
printBloqueTexto(textAdr,1,3,textLength,4)


loadUpperThirdOfScreen()
        
       
         
refreshScreen()
     
 
end sub



sub waitKeyPressAndDepress()
        SetSlot3(6) 
        WHILE INKEY$<>""
            ejecutaSonidoAyWithoutCbank(procesa_una_nota)
        WEND
        
        WHILE INKEY$=""
        
        ejecutaSonidoAyWithoutCbank(procesa_una_nota)
   
        WEND 
        'WHILE INKEY$<>"":WEND
         SetSlot3(0)
end sub

FUNCTION t() AS ULONG
    RETURN 65536 * PEEK (23674) + 256 * PEEK(23673) + PEEK (23672)
END FUNCTION

function  checkTimeForBurbujaDelivery() as ubyte
  dim tiempoActual as long
  dim diferenciaTiempo as long
  tiempoActual = t()
  diferenciaTiempo = TimerBurbujaDelivery - tiempoActual
  if diferenciaTiempo <= 0 then
             return 1
  end if
end function

function getAmountofObjectsToDispose() as uinteger
 dim contador as uinteger
 dim inTheMap as ubyte
 dim tipo as ubyte
 dim objectCounter as ubyte
 contador = OBJ_MAP_HEADER
 WHILE contador < OBJ_START
   inTheMap = peek(contador+1)
   IF inTheMap = 1 or inTheMap = 0 then
        tipo = peek(contador +13)
        'objeto normal, no es un objeto para tirar a la basura
        if tipo =  1 
            objectCounter = objectCounter +1
        end if
   end if
   'change to new section (new object) the object header.
   contador = contador + 15  
 END WHILE
 return objectCounter
end function


function getAmountofObjectsToSort() as uinteger
 dim contador as uinteger
 dim inTheMap as ubyte
 dim tipo as ubyte
 dim objectCounter as ubyte
 contador = OBJ_MAP_HEADER
 WHILE contador < OBJ_START
   inTheMap = peek(contador+1)
   IF  inTheMap = 1 or inTheMap = 0 or inTheMap=3 then
        tipo = peek(contador +13)
        'objeto normal, no es un objeto para tirar a la basura
        if tipo =  0 
            objectCounter = objectCounter +1
        end if
   end if
   'change to new section (new object) the object header.
   contador = contador + 15  
 END WHILE
 return objectCounter
end function

function checkForGameEnd(whatToCheck as ubyte) as ubyte
 dim tiempoActual as long
 dim diferenciaTiempo as long
 dim objectsToSort as ubyte
 dim objectsToDispose as ubyte 

 if whatToCheck then
    objectsToSort    = getAmountofObjectsToSort()
    objectsToDispose = getAmountofObjectsToDispose()
    if not objectsToSort and not objectsToDispose then
        return 2
    end if
 end if
 
 tiempoActual = t()
 diferenciaTiempo = TiempoFinalJuego - tiempoActual
 if diferenciaTiempo <= 0 then
  return 1
 end if
end function



sub endGame(type as ubyte)
 dim offset as ubyte
 dim textAdr as uinteger
 dim textLength as ubyte
 ejecutaSonidoAy(reproductor_en_stop)
 border 0: paper 0 : ink 7
 cls
 
 
 SetSlot3(0)
 cleanMapArtefacts()
 DesactivarBuffer()
 

imprimeWife(12,5)


if type =1 then
    offset = 2
end if
putChars(14, 8 ,2,1,wife_mouth_s+(offset*8))        
PaintData(14,8 ,2,1,wife_mouth_a+offset)

SetSlot3(6)

'win
if type =2 then
    RepAyAddress = cannonBGameMf
    textAdr = t_final_win
else  'lose
    RepAyAddress = gameover
    textAdr= t_final_loose
end if
ejecutaSonidoAy(reproductor_en_play)
SetSlot3(0)
SetSlot3(6)
textLength= 255

printBloqueTexto(textAdr,17,3,textLength,7)



'WHILE INKEY$<>"": WEND
'DO WHILE  INKEY$ = "" 
   'ejecutaSonidoAy(procesa_una_nota)
'Loop
ejecutaSonidoAy(reproductor_en_stop)
SetSlot3(6)
RepAyAddress = song1  'cannonBGameMf

 SetSlot3(0)
 ejecutaSonidoAy(reproductor_en_play)


 cls
end sub

function getObjectInInventory() as uinteger
 dim contador as uinteger
 dim inTheMap as ubyte
 contador = OBJ_MAP_HEADER
 WHILE contador < OBJ_START
   inTheMap = peek(contador+1)
   IF inTheMap = 0 then
      return contador
   end if
   contador = contador + 15  'change to new section (new object) the object header.
 END WHILE
 return 0
end function

FUNCTION binariza(numero as UBYTE) AS UBYTE
    IF numero > 0 then
        numero = 1
    ELSE 
        numero = 0
    END IF
    RETURN numero
END FUNCTION

FUNCTION devuelveValorPosicionBitMap(bitPos AS UINTEGER, adrBitMap as UINTEGER) AS UBYTE
        
   
    DIM charIndex AS UBYTE
    DIM bitInChar AS UBYTE
    DIM bit AS UBYTE
    DIM valorCaracterBitMap AS UBYTE
    DIM mascara AS UBYTE
    
    charIndex           = INT((bitPos - 1) / 8) + 1
    bitInChar           = ((bitPos - 1) MOD 8) + 1   
    mascara             = 1 SHL (8 - bitInChar)
    valorCaracterBitMap = peek(adrBitMap + charIndex-1)          
    bit                 = mascara BAND valorCaracterBitMap
    RETURN bit
    
END function     

/' 
INPUTS
* xPos coordenada x pantalla 0 a 31
* yPos coordenada y  0 a 23
OUTPUT
* retorno  devuelve la posicion en una array de bytes que reprenta la interseccion
entre las coordenadas x e y suministradas.
'/
FUNCTION obtenerPosicionEnMapa(xPos as UBYTE, yPos as UBYTE) AS UINTEGER
 DIM retorno AS UINTEGER
 retorno = CAST(UINTEGER,yPos)*32 + CAST(UINTEGER,xPos) + 1
 RETURN  retorno
END FUNCTION

function getObstructionForAGivenPositionAndLayer (yLayer as ubyte,posicion as uinteger) as ubyte
   dim adrLayer as uinteger
   dim contenido as ubyte
   dim yLayerLocal as ubyte
   dim n as ubyte
    for n = 0 to CantLayersActiveScreen -1
        yLayerLocal = peek(AdrInicioCapasActiveScreen+(97*n))
        if yLayerLocal > yLayer
            contenido =contenido + binariza(devuelveValorPosicionBitMap(posicion,AdrInicioCapasActiveScreen+1+(97*n) ))        
        end if
    next n 
    if contenido > 0 then
        return 1
    else 
        return 0
    end if
end function


function findObjectAdrFromTileValue(valorTile as ubyte) as uinteger
  DIM contador AS UINTEGER
  dim inTheMap as ubyte
  DIM adrObjectData AS UINTEGER
  DIM adrLineStart AS UINTEGER
  DIM valorX, valorY as BYTE
  DIM offset AS UINTEGER
  DIM screenX,screenY AS UBYTE  
  DIM incrementoY AS UBYTE
  DIM lineFirstPosition AS UINTEGER 
  DIM lineQty  AS UBYTE
  DIM objectFirstPosition AS UINTEGER
  DIM n AS UBYTE
  DIM lineOffset AS UBYTE
  dim value as ubyte
  
  contador = OBJ_MAP_HEADER
  
  WHILE contador < OBJ_START
      'cargo valorX y valorY con el x, y de un block
    inTheMap = peek(contador+1)
    IF inTheMap >=1  then
      valorX   = peek(contador+2)
      valorY   = peek(contador+3)            
      IF (valorY = yp) AND (valorX = xp) THEN              
        screenX = PEEK(contador +4)  
        screenY = PEEK(contador +5)
        offset = PEEK(UINTEGER,contador + 10)
        adrObjectData = OBJ_START + offset
        objectFirstPosition = obtenerPosicionEnMapa(screenX,screenY)
        adrLineStart = adrObjectData
        lineQty = 0
        incrementoY = 0
        DO   
           adrLineStart = adrLineStart + CAST(UINTEGER,lineQty)
           lineQty    = PEEK(adrLineStart)
           IF lineQty <> 99 then     
              lineOffset = PEEK(adrLineStart+1)
              FOR n = 0 TO lineQty - 1
                lineFirstPosition = objectFirstPosition +(32*incrementoY)
                'borra al objeto del mapa de objetos
                value = peek(  AdrScreenObjectsTileMap + lineFirstPosition - 1 +  _
                lineOffset + n)
                if value = valorTile then
                    return contador
                end if
              NEXT n
              incrementoY = incrementoY +1
              lineQty = lineQty+2
            ELSE
              EXIT DO
            END IF
          
        LOOP 
      end if
    end if
     contador = contador +15
    
  wend
  return 0
end function


function searchLayerByY(yLayer as ubyte) as uinteger
    dim r as uinteger
    dim yLayerLocal as ubyte
    if  not (CantLayersActiveScreen  = 0) then
        for r = 0 to CantLayersActiveScreen -1
            yLayerLocal = peek(AdrInicioCapasActiveScreen+(97*r))
            if yLayerLocal = yLayer
                return AdrInicioCapasActiveScreen+(97*r)
            end if
        next r
     end if
    return 0
end function
sub setValueInBitMap(bitPos AS UINTEGER, adrBitMap AS UINTEGER, valor AS UBYTE)

    DIM charIndex AS UBYTE
    DIM bitInChar AS UBYTE
    DIM mascara AS UBYTE
    DIM valorCaracterBitMap AS UBYTE

    ' Calculamos en qué byte y qué bit trabajar
    charIndex = INT((bitPos - 1) / 8) + 1
    bitInChar = ((bitPos - 1) MOD 8) + 1
    
    
    

    ' Creamos la máscara para el bit que nos interesa
    mascara = 1 SHL (8 - bitInChar)

    ' Leemos el valor actual del byte
    valorCaracterBitMap = peek(adrBitMap + charIndex - 1)

    ' Dependiendo si queremos poner 0 o 1
    IF valor = 1 THEN
        ' Encender el bit
        valorCaracterBitMap = valorCaracterBitMap bOR mascara
    ELSE
        ' Apagar el bit
        valorCaracterBitMap = valorCaracterBitMap bAND (bNOT mascara)
    END IF

    ' Escribimos el nuevo valor del byte en el bitmap
    poke adrBitMap + charIndex - 1, valorCaracterBitMap

END sub

function getObjectHeight(objectAdr as uinteger) as ubyte
  dim heightObject as ubyte
  dim lineQty as ubyte
  dim adrLineStart as uinteger
  dim offset as uinteger
  
  offset = PEEK(UINTEGER,objectAdr + 10)    'get offset objet data at position 10 of this object section of the header
  adrLineStart = OBJ_START + offset
  DO   
          adrLineStart = adrLineStart + CAST(UINTEGER,lineQty)   'adds the amount of caracter of the previous line to adrLineStart
          lineQty    = PEEK(adrLineStart) 'get the amount of line caract. that is store always in the first position of the line
          IF lineQty <> 99 then     'if the amount of caract. is 99 means no more lines finish painting object
            heightObject = heightObject +1         
            lineQty = lineQty+2
          ELSE
            EXIT DO
          END IF
  LOOP 
  return heightObject
end function


SUB copiaDatosDeUnBancoAOtro(desde as UBYTE, hasta as UBYTE )  
    DIM offset AS UINTEGER = 0
    DIM n AS UBYTE
    FOR n =1 TO 16
         SetSlot3(desde)
         MemCopy(49152+offset,16384,1024)
         SetSlot3(hasta)   
         MemCopy(16384,49152+offset,1024)
         offset = offset +1024
    NEXT n
END SUB


SUB SetSlot3(banco AS UByte)
 dim bankM as ubyte
 bankM = peek $5b5c
 bankM = bankM band %11111000
 bankM = bankM bor banco
 poke $5b5c,bankM
 out $7ffd,bankM
end sub




/'
 INPUTS
 * nroTimer  cada nro de timer esta asociado a una evento determinado
 * ticks  cantidad de retraso que se quiere incluir medido en refrescos de pantalla
 Es decir cada ticks = 20 mls
 OUTPUTS
 * retorna boolean , 1 si se alcanzo la cantidad de ticks desde la ultima testeada y 0 si todavia no
 FUNCIONAMIENTO
  Cada vez que se llama esta funcion se mide cuanto tiempo paso desde la vez anterior que fue llamada y se compara con un valor fijo, si el tiempo que paso es superior a ese valor fijo devuelve 1 sino devuelve 0. Si devuelve 1 tambien actualiza el valor del timer . 
 '/
FUNCTION reachedTime(nroTimer as ubyte,ticks as ubyte) AS ubyte
        'la variable de sistema frames , en su bit menos significativo se ubica
        'en la posicion 23672.
        DIM time AS UBYTE = peek (23672)
        DIM difTime as ubyte
        IF timers(nroTimer) <= time then
            difTime = time - timers(nroTimer)                        
        ELSE
            difTime = (255 - timers(nroTimer) ) + time          
        END IF
        IF difTime >= ticks then 
            timers(nroTimer) = time
            RETURN 1
        ELSE
            RETURN 0
        END IF
        
END FUNCTION



SUB DoubleSize8x8(x AS UBYTE, y AS UByte, dir AS UINTEGER)
    ' Variables locales
    DIM xx, yy, nx, ny, b, a AS UByte
    
    ' En pixels 0,0 está abajo a la izquierda, así que
    ' invertimos el valor de y
    yy = y + 14
    ' 8 filas (8 bytes)
    FOR ny = 0 TO 7
        ' Invertimos x
        xx = x + 14
        ' Leemos el valor del byte
        b = PEEK(dir)
        ' Procesamos el carácter (1 byte)
        FOR nx = 0 TO 7
            ' Cogemos el bit 0
            a = b bAND %1
            ' Desplazamos el byte a la derecha
            b = b >> 1
            ' Si el bit 0 es 0
            IF a = 0 THEN
                ' Modo borrar = 1
                INVERSE 1
            ELSE
                ' Modo borrar = 0
                INVERSE 0
            END IF
            ' Dibujamos 4 puntos (2x2)
            PLOT xx,yy
            PLOT xx+1,yy
            PLOT xx,yy+1
            PLOT xx+1,yy+1
            ' Desplazamos "x" 2 pixels
            xx = xx - 2
        NEXT nx
        ' Siguiente byte
        dir = dir + 1
        ' Desplazamos "y" 2 pixels
        yy = yy - 2
    NEXT ny
    ' Reseteamos el inverse
    INVERSE 0
END SUB


function DoubleSizeTexto(x AS UByte, y AS UByte, texto AS String,modo as ubyte) as ubyte
    DIM dir AS UInteger
    DIM n, c, xx AS UByte
    
    ' Sacamos una copia de x
    xx = x
    ' Recorremos la cadena letra a letra
    FOR n = 0 TO LEN(texto)-1
        ' Dirección del carácter
        dir = PEEK(UInteger, 23606)
        ' Código ASCII del carácter
        c = CODE texto(n)  
        ' Calculamos la dirección del carácter en memoria
        dir = dir + (CAST(UInteger,c) * 8)
        ' Imprimimos el carácter a doble tamaño
        if modo = 1 then
         if  inkey <> "" then       
            return 1
         end if
        end if
        DoubleSize8x8(xx,y,dir)
        
        ' Incrementamos c en 16 pixels
        xx = xx + 16
    NEXT n
END function
